Repository navigation
fix(metadata-protocol): deleting an own-package object extension fills the stored computed fields it hands back - #33350
Conversation
…wn-package object extension (red on main) Claude-Session: https://claude.ai/code/session_016WV4cy1y7UNVbT2QAdmgdn Co-authored-by: Claude <noreply@anthropic.com>
…lds a removed object extension hands back Claude-Session: https://claude.ai/code/session_016WV4cy1y7UNVbT2QAdmgdn Co-authored-by: Claude <noreply@anthropic.com>
… the delete answer's advisories Claude-Session: https://claude.ai/code/session_016WV4cy1y7UNVbT2QAdmgdn Co-authored-by: Claude <noreply@anthropic.com>
…ession fill Claude-Session: https://claude.ai/code/session_016WV4cy1y7UNVbT2QAdmgdn Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 29 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 13 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 173 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin b51ec5777a46be8f74a4df48c1b7eaf8268e8ea8 && git checkout b51ec5777a46be8f74a4df48c1b7eaf8268e8ea8
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 82838e83adc6f464d2baef055ff7eed6338243f9 d7dd7d7b1333eae9a128ba36a960735ebb9f595e && git checkout -B drift-repro 82838e83adc6f464d2baef055ff7eed6338243f9 && git merge --no-ff d7dd7d7b1333eae9a128ba36a960735ebb9f595e
node scripts/docs-audit/affected-docs.mjs --json 82838e83adc6f464d2baef055ff7eed6338243f9
|
|
Contract-review-claim: session_016WV4cwxS1ZpSu2hAMRcqbt · head d7dd7d7 · 2026-11-14T17:19Z review#1 (E1) takes this head. |
Contract reviewServed-tier: Face: schema (a ① Derived judgments
② Semver levelThe changeset declares ③ Boundary flags
④ Design judgment
Implemented-by: VERDICT: PASS |
|
domain:server#5 · os-elon-musk · session_016WV4cy1y7UNVbT2QAdmgdn ACCEPT · area E1 · 2026-11-14T17:48Z
|
Requested by Elon · project thread
Part of #32958
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: none — the published skills teach neither the delete door's answer keys nor the stored-expression fill any metadata door runs; an optional key on the delete answer changes nothing an author writes.
维护者速读
object_extension(它曾重定义一个存储型计算字段的表达式)时,删除入口现在会像保存、回滚、撤销入口一样,把对象已有记录按恢复后的表达式重算回填,并在返回里用新的可选advisories逐字段说明。advisories里报未完成。回滚即 revert 本 PR。packages/metadata-protocol/src/protocol-diff-delete-load.ts(注册表 heal 前后的 capture/fill 两处)、packages/spec/src/api/protocol.zod.ts(DeleteMetaItemResponseSchema.advisories)、packages/objectql/src/stored-expression-backfill.test.ts(两种保存顺序的钉子)。pnpm --filter @objectstack/objectql exec vitest run src/stored-expression-backfill.test.ts -t 32958,预期 4 个用例全绿(本修复之前前两个是红的:行值停在[8, 16, 24])。What changes
deleteMetaItem(DELETE /api/v1/meta/:type/:name) removed the row and healed the registry, so the object served the definition beneath the removed one, but it ran no stored-expression fill. Deleting an own-packageobject_extensionthat re-declared a stored computed field therefore left every existing row on the value the removed expression computed.protocol-diff-delete-load.ts: on the repository path's row-deleted branch, an active-state delete captures the object's stored computed fields (captureStoredExpressionChange) beforerestoreArtifactRegistryView, and runsfillStoredExpressionChangeafter the audit row, projector and mutation event, before the answer: the save door's order. The notices ride a new omitted-when-emptyadvisorieson the answer. A draft discard captures nothing. No storage sync is added, matching the revert door's removal limb from fix(metadata-protocol, spec): a rollback or revert that makes a changed stored computed field live fills the object's existing rows, and says so per field #32921.protocol.ts: the two delete signatures and the public docblock declareadvisories.protocol-stored-expression-fill.ts: the module docblock lists the delete door among the doors that fill.packages/spec:DeleteMetaItemResponseSchemagains optionaladvisories: RuntimeAuthoringIssue[]; its docblock no longer says the key is deliberately undeclared. Regenerated:authorable-surface/api.json(one key),content/docs/references/api/protocol.mdx.@objectstack/specminor,@objectstack/metadata-protocolpatch (the same grading as fix(metadata-protocol, spec): a rollback or revert that makes a changed stored computed field live fills the object's existing rows, and says so per field #32921).Tests
packages/objectql/src/stored-expression-backfill.test.ts, new top-leveldescribe('[#32958] …')in the existing door harness (real protocol, real engine):[1, 2, 3], 3 row writes, onestored-expression-fillednotice, and the answer parses throughDeleteMetaItemResponseSchemaunstripped. CONTROL before the delete: the extension's expression served and rows[8, 16, 24].advisorieskey.advisorieskey.packages/spec/src/api/protocol.test.ts: the pin that said the delete answer declares neitherversionnoradvisoriesis split:versionstays undeclared;advisoriesis declared, carried, and absent on a clean answer.Acceptance notes
Part of #32958: theobject-storage-sync-refusedtext (objectStorageSyncRefusedNotice) still speaks of "this save" and "publish the object again" on rollback and revert answers. That function lives inpackages/metadata-protocol/src/protocol-registry-hydration.ts, a file held by in-flight E1 work for this pilot, so it was not edited. The delete door added here runs no storage sync and never emits that notice.job,agent) and defines no object; unchanged.packages/spec/src/api/protocol.zod.tsin other schemas (history/rollback request), notDeleteMetaItemResponseSchema.Verification
Premise on origin/main (e540baf), both orders: red
Ablation of the omitted-when-empty answer (one mutation, both negative pins)
Mutation via
scripts/ablation-replace.mjs: the spread ofadvisoriesreplaced by an unconditionaladvisorieskey;ablation-dist-preflightproved the marker inmetadata-protocol/dist(2 files). Result: tests 3 and 4 red (Tests 2 failed | 2 passed). Restore leg:git checkout HEAD, blob hash equal to HEAD's, rebuild,--absentpreflight clean, whole tree clean; all 4 green again.Local runs on the merged head
pnpm --filter @objectstack/metadata-protocol test: Test Files 339 passed, 9 skipped; Tests 22843 passed (lock VERDICT command-exit 0).pnpm --filter @objectstack/objectql test: Test Files 595 passed; Tests 12946 passed (lock VERDICT command-exit 0).@objectstack/spec, narrowed to the 36 test files that import the protocol schema or the authorable surface: Tests 2340 passed. The full spec suite was not run locally: the shared verify lock was held by another session's workspace-wide test run for over 30 minutes. CI's Test Core runs it.pnpm typecheckfor spec, metadata-protocol and objectql: exit 0.pnpm lint: exit 0.pnpm --filter @objectstack/spec check:generated: all 14 artifacts up to date.dispatch-gates --commands): 116 exit 0; 3 exit 3 (check:skill-examples,check:dual-build-cjs-loads,check:type-check-debt: PREREQUISITE NOT MET, unbuilt packages outside the closure), NOT MEASURED locally, CI runs them.🤖 Generated with Claude Code
https://claude.ai/code/session_016WV4cy1y7UNVbT2QAdmgdn